package com.sac.approval.service.impl;

import com.sac.approval.dao.ApprovalDao;
import com.sac.approval.dao.ApprovalLineDao;
import com.sac.approval.dao.AttachmentDao;
import com.sac.approval.domain.ApprovalDO;
import com.sac.approval.domain.ApprovalLineDO;
import com.sac.approval.domain.AttachmentDO;
import com.sac.approval.domain.DelegateMappingDO;
import com.sac.approval.enums.ApprovalLineStatusEnum;
import com.sac.approval.enums.ApprovalRoleEnum;
import com.sac.approval.enums.ApprovalStatusEnum;
import com.sac.approval.service.*;
import com.sac.common.utils.WebSocketUtil;
import com.sac.emp.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.context.Context;

import java.util.*;


@Service
public class ApprovalServiceImpl implements ApprovalService {
	@Autowired
	private ApprovalDao approvalDao;
	
	@Autowired
	private ApprovalLineDao approvalLineDao;
	
	@Autowired
	private AttachmentDao attachmentDao;

	@Autowired
	private EmailService emailService;

	@Autowired
	private EmpService empService;

	@Autowired
	private ApprovalLineService approvalLineService;

	@Autowired
	private ApprovalQueryService approvalQueryService;

	@Autowired
	private DelegateMappingService delegateMappingService;
	
	@Override
	public int count(Map<String, Object> map){
		return approvalDao.count(map);
	}
	
	@Override
	public int save(ApprovalDO approval){
		return approvalDao.save(approval);
	}
	
	@Override
	public int update(ApprovalDO approval){
		return approvalDao.update(approval);
	}

	@Override
	@Transactional
	public int batchUpdate(List<ApprovalDO> approvalList) {
		approvalList.forEach(s-> approvalDao.update(s));
		return approvalList.size();
	}

	@Override
	@Transactional
	public int cancelSubmission(ApprovalDO approval, ApprovalLineDO line) {
		approvalDao.update(approval);
		approvalLineDao.update(line);
		return 0;
	}

	@Override
	public int remove(String appId){
		return approvalDao.remove(appId);
	}
	
	@Override
	public int batchRemove(String[] appIds){
		return approvalDao.batchRemove(appIds);
	}

	@Override
	@Transactional
	public int createApproval(ApprovalDO approval, List<ApprovalLineDO> appLines, List<AttachmentDO> attachments) {
		int i = approvalDao.save(approval);
		appLines.forEach(line-> approvalLineDao.save(line));
		attachments.forEach(attachment-> attachmentDao.save(attachment));

		return i;
	}

	@Override
	@Transactional
	public int updateApproval(ApprovalDO approval, List<ApprovalLineDO> appLines, List<AttachmentDO> attachments) {
		int i =update(approval);
		approvalLineDao.removeByAppId(approval.getAppId());
		appLines.forEach(line-> approvalLineDao.save(line));
		attachmentDao.removeByAppId(approval.getAppId());
		attachments.forEach(attachment-> attachmentDao.save(attachment));
		return i;
	}

	@Override
	@Async
	public void sendEmail(List<ApprovalLineDO> lineList, ApprovalDO app) {
		//提交审批发送邮件
		Context context = new Context();
		context.setVariable("author", empService.getEmpDetailInfo(app.getCreateUser()).getEmpNm());
		context.setVariable("submitTime", app.getCreateTime());
		context.setVariable("status", app.getStatusName());
		context.setVariable("title", app.getTitle());
//		context.setVariable("contents", app.getContent());
		lineList.forEach(receiver -> {
			// 发送邮件
			emailService.sendTemplateMail(receiver.getReceiverMail(), "[Official] [Approve Notification] "+app.getTitle(), context, "mail/mailTemplate",
					null);
			receiver.setMailDeliveryStatus("Y");
		});
		approvalLineService.batchUpdate(lineList);
	}

	@Override
	public void pushPendingNotification(List<ApprovalLineDO> lineList, ApprovalDO app) {
		Date date = new Date();
		//提交审批发送邮件
		lineList.forEach(receiver -> {
			receiver.setReceiptTime(date);
			DelegateMappingDO delegate = delegateMappingService.getValidDelegate(receiver.getReceiverEpid());
			if(delegate != null){
				receiver.setAgentUserId(delegate.getAgentUserId());
				WebSocketUtil.pushPendingNotification(delegate.getAgentUserId(), "您收到一封审批邮件，请查看！");
			}else{
				WebSocketUtil.pushPendingNotification(receiver.getReceiverEpid(), "您收到一封审批邮件，请查看！");
			}
		});
		approvalLineService.batchUpdate(lineList);
	}

	@Override
	@Transactional
	public void handleApprove(Map<String, Object> params) {
		Date date = new Date();
		String appId = params.get("appId").toString();
        String appLineId = params.get("appLineId").toString();
        String remark = params.get("remark").toString();
        //获取审批邮件
        ApprovalDO approval = approvalQueryService.getApproval(appId);
        //修改line状态，保存备注
        ApprovalLineDO line = approvalQueryService.getApprovalLine(appLineId);
        line.setStatus(ApprovalLineStatusEnum.APPROVED.getValue());
        line.setRemark(remark);
		line.setHandleTime(date);
		approvalLineService.update(line);
		//获取后面的审批人列表
        List<ApprovalLineDO> pendingLineList = approvalQueryService.getPendingApproverList(appId);
		//判断是否后批，若后批
        List<ApprovalLineDO> postLineList = approvalQueryService.listLines(new HashMap<String,Object>(){{
            put("appId",appId);
            put("handleType",ApprovalRoleEnum.POST_APPROVAL.getValue());
        }});
		//获取通知人列表
        List<ApprovalLineDO> notifierLineList = approvalQueryService.listLines(new HashMap<String,Object>(){{
			put("appId",appId);
			put("handleType",ApprovalRoleEnum.NOTIFICATION.getValue());
		}});
        if(pendingLineList.size()==0){
            //作为最后一个审批人，审批完成
            approval.setStatus(ApprovalStatusEnum.APPROVED.getValue());
            approval.setCompleteNum(UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
            notifierLineList.forEach(notifier->{
            	notifier.setReceiptTime(date);
            	approvalLineService.update(notifier);
			});
        }else{
            if(postLineList.size()>0){
                //后批邮件
                List<ApprovalLineDO> pendingSimpleLineList = approvalQueryService.getPendingSimpleApproverList(appId);
                if(pendingSimpleLineList.size()==1 && line.getHandleType()!=ApprovalRoleEnum.POST_APPROVAL.getValue()){
                    //普通审批正在结束，最后一个普通审批
                    approval.setStatus(ApprovalStatusEnum.POST_APPROVAL.getValue());
                }
            }
        }

        this.update(approval);

        //邮件逻辑
		//简单审批，进入下一个节点
		//平行审批，如果是最后一个审批人，则进入下一个节点；否则等他其他人审批
        //后批则给后批后面的同时发送邮件
        //发送邮件到后面节点

        List<ApprovalLineDO> notifyReceiverList = new ArrayList<>();
        List<ApprovalLineDO> pendingReceiverList = new ArrayList<>();
        if(pendingLineList.size()==0){
            //作为最后一个审批人，审批完成
            //都审批完成后，根据通知范围发送邮件通知
            notifyReceiverList = approvalQueryService.listLines(new HashMap<String,Object>(){{
                put("appId",appId);
            }});
            sendEmail(notifyReceiverList,approval);
        }else{
            if(line.getHandleType()== ApprovalRoleEnum.PARALLEL_APPROVAL.getValue() || line.getHandleType()==ApprovalRoleEnum.PARALLEL_CONSENT.getValue()){
                //平行审批
                if(pendingLineList.get(0).getSeq() != line.getSeq()){
                    //平行审批结束,发送邮件
                    pendingReceiverList = pendingLineList;
                }
            }else{
                //简单审批
                pendingReceiverList = pendingLineList;
            }
            sendEmail(pendingReceiverList,approval);
            // 异步发送通知
			pushPendingNotification(pendingReceiverList,approval);
        }
	}

	/**
     * 特批
     * @param params
     */
	@Override
	@Transactional
	public void handleArbi(Map<String, Object> params) {
		Date date = new Date();
		//判断简单/平行审批
		//如果是简单审批，结束流程（修改line状态，修改其他人审批状态为已审批，修改master状态）
		//如果是平行审批，则跳出此节点（修改同级别节点状态为已审批），进入下一节点继续审批
		//发送邮件通知
        String appId = params.get("appId").toString();
        String appLineId = params.get("appLineId").toString();
        String remark = params.get("remark").toString();
        //获取审批邮件
        ApprovalDO approval = approvalQueryService.getApproval(appId);
        //修改line状态，保存备注
        ApprovalLineDO line = approvalQueryService.getApprovalLine(appLineId);
        line.setHandleTime(date);
        line.setStatus(ApprovalLineStatusEnum.ARBITRARY.getValue());
        line.setRemark(remark);
        approvalLineService.update(line);
        //获取后面的审批人列表
        List<ApprovalLineDO> pendingLineList = approvalQueryService.getPendingApproverList(appId);
		//获取通知人列表
        List<ApprovalLineDO> notifierLineList = approvalQueryService.listLines(new HashMap<String,Object>(){{
			put("appId",appId);
			put("handleType",ApprovalRoleEnum.NOTIFICATION.getValue());
		}});

        if(pendingLineList.size()==0){
			arbiEndApproval(approval,appId,notifierLineList);
        }else{
            if(line.getHandleType()==ApprovalRoleEnum.PARALLEL_APPROVAL.getValue() || line.getHandleType()==ApprovalRoleEnum.PARALLEL_CONSENT.getValue()){
                //平行审批
                if(pendingLineList.get(0).getSeq() != line.getSeq()){
                    //平行审批结束,发送邮件
                }else{
                    pendingLineList.forEach(pendingLine->{
                        pendingLine.setStatus(ApprovalLineStatusEnum.AUTO_APPROVED.getValue());
						pendingLine.setHandleTime(date);
                    });
                }
                // 异步发送邮件和通知
				sendEmail(pendingLineList,approval);
				pushPendingNotification(pendingLineList,approval);

				pendingLineList = approvalQueryService.getPendingApproverList(appId);
				if(pendingLineList.size()==0){
					arbiEndApproval(approval,appId,notifierLineList);
				}
            }else{
                //简单审批,结束审批
				arbiEndApproval(approval,appId,notifierLineList);
            }
        }

        this.update(approval);
	}

	/**
	 * 结束审批
	 */
	@Transactional
	public void arbiEndApproval(ApprovalDO approval,String appId, List<ApprovalLineDO> notifierLineList) {
		Date date = new Date();
		approval.setStatus(ApprovalStatusEnum.ARBITRARY.getValue());
		approval.setCompleteNum(UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
		//邮件列表
		List<ApprovalLineDO> notifyReceiverList = approvalQueryService.listLines(new HashMap<String,Object>(){{
			put("appId",appId);
		}});
		notifierLineList.forEach(notifier->{
			notifier.setReceiptTime(date);
			approvalLineService.update(notifier);
		});
		sendEmail(notifyReceiverList,approval);
	}

	/**
     * 驳回
     * @param params
     */
	@Override
	@Transactional
	public void handleReject(Map<String, Object> params) {
		Date date = new Date();
        String appId = params.get("appId").toString();
        String appLineId = params.get("appLineId").toString();
        String remark = params.get("remark").toString();
        //修改line状态，保存备注
        ApprovalLineDO line = approvalQueryService.getApprovalLine(appLineId);
        line.setHandleTime(date);
        line.setStatus(ApprovalLineStatusEnum.REJECT.getValue());
        line.setRemark(remark);
        approvalLineService.update(line);
        //获取审批邮件
        ApprovalDO approval = approvalQueryService.getApproval(appId);
        approval.setStatus(ApprovalStatusEnum.REJECT.getValue());
        update(approval);
        //获取通知人列表
        List<ApprovalLineDO> notifierLineList = approvalQueryService.listLines(new HashMap<String,Object>(){{
			put("appId",appId);
			put("handleType",ApprovalRoleEnum.NOTIFICATION.getValue());
		}});
        notifierLineList.forEach(notifier->{
			notifier.setReceiptTime(date);
			approvalLineService.update(notifier);
		});
        //发送邮件给所有人
		List<ApprovalLineDO> receiverList = new ArrayList<>();
		receiverList = approvalQueryService.listLines(new HashMap<String,Object>(){{
                put("appId",appId);
            }});

        //异步发送邮件
		sendEmail(receiverList,approval);
	}

}
